/*
 * Copyright (c) 2024 Huawei Technologies Co.,Ltd.
 *
 * openGauss is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 * http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * -------------------------------------------------------------------------
 *
 * htap_flush.h
 * API for the HTAP Flush
 *
 * IDENTIFICATION
 * src/include/storage/htap/htap_flush.h
 *
 * -------------------------------------------------------------------------
 */

#ifndef HTAP_FLUSH_H
#define HTAP_FLUSH_H

#include "htap_common.h"
#include "gs_thread.h"
#include <mutex>
#include "access/imcs/imcu.h"
#include "access/imcs/imcs_insert.h"
#include "table.h"
#include "htap_flush_worker.h"

#define MAX_TABLES_IN_STATS 1000
#define MAX_WORKERS_THREAD 100

namespace htap {
typedef struct tbl_stats_t {
    int tbl_id;
    int64 insert_time;
    int64 delete_time;
    int64 total_time;
    int num_new_rg;
    int num_delete_rgs;
    uint64 num_rows;
    int32 num_deleted;
} tbl_stats_t;

enum TaskType {
    DELTA_DELETE = 0,
    DELTA_INSERT = 1,
    DELTA_COMPLETE = 2
};

class FlushTask : public BaseObject {
public:
    FlushTask(TaskType tt, HTAPFlushCtx *table_ctx, int rg_idx, int free_rows, uint64_t opaque)
        : task_type(tt), table_ctx(table_ctx), rg_idx(rg_idx), free_rows(free_rows), opaque(opaque)
    {}
    void Destroy() {}
    TaskType task_type;
    HTAPFlushCtx *table_ctx;
    int rg_idx;
    int free_rows;
    uint64_t opaque;
};

class FlushTaskQueue {
public:
    FlushTaskQueue()
    {
        m_queue_size = 0;
    }
    void Add(FlushTask *task);
    FlushTask *Get();
    bool Empty();
    bool IsFinished();
    void SetFinished(FlushTask *task);
    void CleanFinished();
    // private:
    /** @var Lock to serialize tasks management. */
    std::mutex m_lock;

    /** @var Lock to serialize finished management. */
    std::mutex m_finished_lock;

    list<FlushTask *> m_queue;
    uint32_t m_queue_size;
    list<FlushTask *> m_finished_queue;
};

class HTAPFlush {
public:
    /** @brief Creates the single flush instance. */
    static bool CreateInstance();

    /** @brief Destroys the single flush instance. */
    static void DestroyInstance();

    /** @brief Retrieves reference to the single flush instance. */
    static HTAPFlush *GetInstance();

    bool InitFlush();

    /* *
     * @brief Launches the flush thread.
     * @param threadId The resulting flush thread identifier.
     * @return @ref HTAP_RC_OK if succeeded, otherwise error code.
     */
    RC Start(ThreadId &threadId);

    /* *
     * @brief Orders the flush thread to stop. This is a blocking call that waits until the flush thread stops.
     * @return @ref HTAP_RC_OK if succeeded, otherwise error code.
     */
    RC Stop();

    /** @brief Queries whether the flush thread is currently running. */
    bool IsRunning();

    /** @brief Retrieves the flush thread id. */
    ThreadId GetThreadId();

    /** @brief Executes the flush thread's main loop. */
    void ExecFlush();
    void RunWorker();
    void StopWorkers(bool shouldWait = false);
    void addTable(MOT::Table *table);
    void flushPrintTablesStats();
    FlushTaskQueue *getWorkingQueue()
    {
        return &m_task_queue;
    }
    const char *GetDbName()
    {
        return m_dbname.c_str();
    }
    uint64_t GetLastFlushedCSN()
    {
        return m_lastFlushdCSN;
    }

private:
    /** @brief Constructor. */
    HTAPFlush();

    /** @brief Destructor. */
    ~HTAPFlush();

    /** @var The single instance. */
    static HTAPFlush *m_flush;

    /** @var Flush thread identifier. */
    ThreadId m_flushThread;

    /** @var Flush thread state. */
    bool m_isRunning;

    char m_user_name[NAMEDATALEN];
    std::string m_dbname;
    bool m_confEnableFlush;
    bool m_conf_enable_print_stats;

    int m_num_workers;

    tbl_stats_t m_tbl_stats[MAX_TABLES_IN_STATS];

    HTAPFlushWorker *m_workers[MAX_WORKERS_THREAD];
    ThreadId m_workers_thread_id[MAX_WORKERS_THREAD];
    bool m_workers_running[MAX_WORKERS_THREAD];

    /** @var Working Queue of Flush Tasks */
    FlushTaskQueue m_task_queue;

    std::list<uint64_t> tableList;

    /** @var Lock to serialize thread state management. */
    std::mutex m_lock;

    /** @var Memory controller */
    MemoryContext m_memory_ctx;

    /** @var Cycle Memory controller - created and released each cycle */
    MemoryContext m_flush_ctx;

    /** @var Relation object of the current table */
    uint64_t m_lastFlushdCSN;
    uint64_t m_prevFlushdCSN;

    /** @brief Initializes the flush thread. */
    void InitFlushThread();

    /** @brief Executes a single flush cycle. */
    bool Flush(CommitSeqNo csn);

    /* *
     * @brief Queries whether the flush thread was signaled to stop.
     * @param timeoutMillis The timeout in milliseconds to wait for the stop latch to be signaled.
     * @return True if the flush thread was signaled to stop, otherwise false.
     * @note This is a blocking call for the specified timeout.
     */
    bool SignaledToStop(uint64_t timeoutMillis);

    void MoveDeltaDataToCU(HTAPFlushCtx *table_ctx);
    void MarkDeleteToIMCU(HTAPFlushCtx *table_ctx);
    void AddDeltaDataToIMCU(HTAPFlushCtx *ctx);
    void FlushDeltaTableToIMCU(HTAPFlushCtx *ctx);
    bool setupVariablesForMoveDeltaDataToCU(HTAPFlushCtx *table_ctx);
    bool checkDeltaInCURange(IMCUDesc *cu_desc, HTAPFlushCtx *table_ctx);

    TupleDesc initImcsTupleDesc(Relation rel, MOT::Table *table);
};

} // namespace htap
#endif // HTAP_FLUSH_H
